
class Agent(object):
    
    NAME = "RRbot"
    
    def __init__(self, id, team, settings=None, field_rects=None, field_grid=None, nav_mesh=None, blob=None, **kwargs):
        """ Each agent is initialized at the beginning of each game.
            The first agent (id==0) can use this to set up global variables.
            Note that the properties pertaining to the game field might not be
            given for each game.
        """
        self.id = id
        self.team = team
        self.mesh = nav_mesh
        self.grid = field_grid
        self.settings = settings
        self.goal = None
        self.callsign = '%s-%d'% (('BLU' if team == TEAM_BLUE else 'RED'), id)
        self.kills = 0
        self.death = 0
        self.deathCheck = False
        
        # Read the binary blob, we're not using it though
        if blob is not None:
            print "Agent %s received binary blob of %s" % (
               self.callsign, type(pickle.loads(blob.read())))
            # Reset the file so other agents can read it.
            blob.seek(0) 
        
        # Recommended way to share variables between agents.
        if id == 0:
            self.all_agents = self.__class__.all_agents = []
        self.all_agents.append(self)
    
    def observe(self, observation):
        """ Each agent is passed an observation using this function,
            before being asked for an action. You can store either
            the observation object or its properties to use them
            to determine your action. Note that the observation object
            is modified in place.
        """
        self.observation = observation
        self.selected = observation.selected

        if observation.selected:
            print observation
#agent 0 and 1 goto CP, last agent goes for ammo and kills                    
    def action(self):
        """ This function is called every step and should
            return a tuple in the form: (turn, speed, shoot)
        """

        
        obs = self.observation
        lastHit = obs.hit
        if lastHit is not None and lastHit is not self.team:
            self.kills += 1
        
        
        if obs.respawn_in < 1:
            self.deathCheck = False
        
        if obs.respawn_in  > 0 and self.deathCheck is False:
            self.death += 1 
            self.deathCheck = True
            
        print self.death
         
        for x in range(len(self.all_agents)):
            if x is not id:
                if self.goal is not None and self.all_agents[x].goal is not None and self.goal == self.all_agents[x].goal:
                    self.goal = None
                
        gotAllPoints = self.checkPoints()         
        
        shoot = False
        #shoot enemies
        if (obs.ammo > 0 and 
            obs.foes and 
            point_dist(obs.foes[0][0:2], obs.loc) < self.settings.max_range and
            not line_intersects_grid(obs.loc, obs.foes[0][0:2], self.grid, self.settings.tilesize)):
            self.goal = obs.foes[0][0:2]
            shoot = True
                     
        # Check if agent reached goal.
        if self.goal is not None and point_dist(obs.loc, self.goal) < self.settings.tilesize*2:#if you are very NEAR the goal
            for x in range(len(obs.foes)):#for all enemies check if it is close
                if point_dist(obs.  foes[x][0:2], obs.loc) < self.settings.tilesize*2:
                    self.goal = None
                    
        if self.goal is not None and point_dist(self.goal, obs.loc) < self.settings.tilesize:
                self.goal = None
 

        if self.goal is None:
            #for x in range(0, len(obs.cps)):
            if(self.id < 2):
                self.goal = obs.cps[self.id][0:2]
            else:
                if obs.ammo == 0:
                    self.goal = self.getAmmoSpot()
                    
                    
        #walk to CP that is not ours
        if self.goal is None:
            for x in range(0, len(obs.cps)):
                if(obs.cps[x][2] != 0):
                    self.goal = obs.cps[x][0:2] 
         
        if self.goal is None:
            self.goal = obs.cps[random.randint(0,len(obs.cps)-1)][0:2]
               
               
        #shoot enemies
        if (obs.ammo > 0 and gotAllPoints and
            obs.foes and 
            point_dist(obs.foes[0][0:2], obs.loc) < self.settings.max_range and
            not line_intersects_grid(obs.loc, obs.foes[0][0:2], self.grid, self.settings.tilesize)):
            self.goal = obs.cps[random.randint(0,len(obs.cps)-1)][0:2]
            shoot = True

        # Compute path, angle and drive 
        path = find_path(obs.loc, self.goal, self.mesh, self.grid, self.settings.tilesize)
        if path:
            dx = path[0][0] - obs.loc[0]
            dy = path[0][1] - obs.loc[1]
            turn = angle_fix(math.atan2(dy, dx) - obs.angle)
            speed = self.settings.max_speed#10*(dx**2 + dy**2)**0.5
            if turn > self.settings.max_turn or turn < -self.settings.max_turn:
                shoot = False
                (dx**2 + dy**2)**0.5
            if turn > 1.5*self.settings.max_turn or turn < 1.5*-self.settings.max_turn:
                shoot = False
                
                
        else:
            turn = 0
            speed = 0

        
        return (turn,speed,shoot)
    
    
    
    def getClosestCP(self):
        shortest_distance = 999999
        best_index = -1
        for i in range(len(obs.cps)):
            dist = point_dist(obs.loc, 
                obs.cps[i][0:2])
            if shortest_distance > dist:
                shortest_distance = dist
                best_index = i
   
        # this should never happen! 
        if best_index < 0:
            return False
       
       
        return obs.cps[best_index]
        
    def someoneOnPoint(self,ownindex,CP):
        for x in range(len(self.all_agents)):
            if ownindex == x:
                continue
            if point_dist(self.all_agents[x].observation.loc, CP[0:2]) < self.settings.tilesize:
                return True
            else:
                return False 
            
    def checkPoints(self):
        gotAllPoints = False
          #Check for CPs
        for x in range(0, len(self.observation.cps)):
            if(self.observation.cps[x][2] == 0):
                 gotAllPoints = True
                 continue
            else:
                 gotAllPoints = False
                 return gotAllPoints
            return gotAllPoints      

    def getAmmoSpot(self):
        # Walk to ammo
        ammopacks = filter(lambda x: x[2] == "Ammo", self.observation.objects)
        if ammopacks:
           return ammopacks[0][0:2]
    
    def set_goal_to_shoot(self, id):#taken from waard.py
        self.agents[id].shoot = False
        if (self.agents[id].observation.ammo > 0 and 
            self.agents[id].observation.foes and 
            point_dist(self.agents[id].observation.foes[0][0:2], self.agents[id].observation.loc) < self.agents[id].settings.max_range and
            not line_intersects_grid(self.agents[id].observation.loc, self.agents[id].observation.foes[0][0:2], self.agents[id].grid, self.agents[id].settings.tilesize)):
            # Check if an ally is in the way
            print "bot %s shooting enemy %s" % (self.agents[id].id, self.agents[id].observation.foes[0])
            # Don't shoot friends!
            for friend in self.agents[id].observation.friends:
                if(line_intersects_circ(self.agents[id].observation.loc, self.agents[id].observation.foes[0][0:2], friend, 6)):
                    return False
            self.agents[id].goal = self.agents[id].observation.foes[0][0:2]
            self.agents[id].shoot = True
            return True
        return False
    def debug(self, surface):
        """ Allows the agents to draw on the game UI,
            Refer to the pygame reference to see how you can
            draw on a pygame.surface. The given surface is
            not cleared automatically. Additionally, this
            function will only be called when the renderer is
            active, and it will only be called for the active team.
        """
        import pygame
        # First agent clears the screen
        if self.id == 0:
            surface.fill((0,0,0,0))
        # Selected agents draw their info
        if self.selected:
            if self.goal is not None:
                pygame.draw.line(surface,(0,0,0),self.observation.loc, self.goal)
        
        PRINTMESH = True		
        if PRINTMESH:
            for n1 in self.mesh:
                for n2 in self.mesh[n1]:
                    pygame.draw.line(surface,(120,180,120),n1,n2,2)
                    pygame.draw.circle(surface,(120,180,120),n1,3)
        
        
    def finalize(self, interrupted=False):
        """ This function is called after the game ends, 
            either due to time/score limits, or due to an
            interrupt (CTRL+C) by the user. Use it to
            store any learned variables and write logs/reports.
        """
        pass
        
